package state.component;

import java.util.Vector;

import state.GameConstants;
import state.GameImage;
import state.Graphics;
import state.Key;
import state.Manager;
import state.ResourceManager;
import state.Sprite;
import state.TimerListener;
import state.bean.GamePoint;
import state.bean.GameRect;
import state.font.FontManager;
import state.font.ImageFont;
import state.util.GameColor;
import state.util.ImageUtil;
import state.util.TwoDimensionString;
import state.util.array.GameImageArray;
import state.util.array.IntArray;
import state.util.array.ObjectArray;
import state.util.array.StringArray;
import stateframework_particle.view.StateFramework_ParticleResources;

public class GridMenu extends Component implements TimerListener {
  private GameRect gridBorder = null;
  private int dx = 0;
  private int dy = 0;
  private int borderY = 0;
  private int hozDistance = 0;
  private int verDistance = 0;
  private int numberOfItemPerRow = 0;

  private Vector items = null; // Sprite
  private Vector images = null; // Image
  private Vector brightImages = null; // Image
  private Vector titles = null;
  private TwoDimensionString tootltip = null;
  private IntArray eventNumbers = null;
  private GameImage roundRedImage = null;

  private int brightLevel = 3;
  private int currentSelectedIndex = 0;
  private int stopTime = 0;
  private int showToolTipTime = 1000;
  private boolean displayTitle = false;
  private MultiTab multiTab = null;
  private boolean isNextTabWhenEndRow = false;
  private boolean isBackTabWhenBeginRow = false;
  private int initDy = 0;
  private boolean enableScroll = false;

  private GamePoint pressedPoint = new GamePoint(0, 0);
  private int timePressed = 0;
  private int rowMove = 0;

  private ImageFont text8 = null;

  private EventListener eventListener = null;

  public GridMenu(Manager manager, ObjectArray images1, StringArray titles1, int numberOfItemPerRow1, int dx1, int dy1, int hozDistance1, int verDistance1, EventListener eventListener1) {
    super(manager, 0, 0, GameConstants.SCREEN_WIDTH, GameConstants.SCREEN_HEIGHT);
    setManager(manager);
    this.dx = dx1;
    this.dy = dy1;
    this.initDy = dy1;
    this.hozDistance = hozDistance1;
    this.verDistance = verDistance1;
    this.numberOfItemPerRow = numberOfItemPerRow1;
    this.borderY = dy1 - verDistance1 / 2;
    enableScroll = true;

    // Init image
    this.images = new Vector();
    brightImages = new Vector();
    if (images1 != null) {
      for (int i = 0; i < images1.len(); i++) {
        this.images.addElement(images1.get(i));
        brightImages.addElement(ImageUtil.makeBrighter((GameImage) images1.get(i), brightLevel));
      }
    }

    // Create items
    items = new Vector();
    for (int i = 0; i < this.images.size(); i++) {
      int x1 = dx1 + hozDistance1 * (i % numberOfItemPerRow1);
      int y1 = dy1 + verDistance1 * (i / numberOfItemPerRow1);
      items.addElement(new Sprite((GameImage) images1.get(i), null, x1, y1, GameConstants.CENTER_ANCHOR));
    }

    // Create title
    this.titles = new Vector();
    if (titles1 != null && titles1.len() > 0) {
      for (int i = 0; i < titles1.len(); i++) {
        this.titles.addElement(titles1.get(i));
      }
      displayTitle = true;
    } else {
      displayTitle = false;
    }

    this.eventListener = eventListener1;
    roundRedImage = new GameImage(StateFramework_ParticleResources.image_nen_do, null, null).setStatic(true);
    text8 = FontManager.getFont(FontManager.FONT_SIZE_8);
    _hasBorder = false;
    gridBorder = new GameRect(dx1, dy1, hozDistance1 * numberOfItemPerRow1, verDistance1 * (items.size() / numberOfItemPerRow1));
    setTimerListener(this);
  }

  public void clearData() {
    if (items != null) {
      items.removeAllElements();
    }
    if (images != null) {
      images.removeAllElements();
    }
    if (brightImages != null) {
      brightImages.removeAllElements();
    }
    if (titles != null) {
      titles.removeAllElements();
    }
    gridBorder._width = 0;
    gridBorder._height = 0;
    displayTitle = false;
    currentSelectedIndex = 0;
    dy = initDy;
  }

  public void addImageItem(GameImage image1, String title) {
    int x1 = dx + hozDistance * (items.size() % numberOfItemPerRow);
    int y1 = dy + verDistance * (items.size() / numberOfItemPerRow);
    images.addElement(image1);
    brightImages.addElement(ImageUtil.makeBrighter(image1, brightLevel));
    items.addElement(new Sprite(image1, null, x1, y1, GameConstants.CENTER_ANCHOR));

    if (title != null && titles != null) {
      titles.addElement(title);
    }
    gridBorder._width = hozDistance * numberOfItemPerRow;
    gridBorder._height = verDistance * (items.size() / numberOfItemPerRow);
  }

  public void addSpriteItem(Sprite sprite, String title) {
    int x1 = dx + hozDistance * (items.size() % numberOfItemPerRow);
    int y1 = dy + verDistance * (items.size() / numberOfItemPerRow);
    sprite.setPosition(x1, y1);

    GameImage image1 = sprite.getImage();
    if (image1 == null) {
      image1 = ResourceManager.createEmptyImage();
    }
    images.addElement(image1);
    brightImages.addElement(ImageUtil.makeBrighter(image1, brightLevel));
    items.addElement(sprite);

    if (title != null && titles != null) {
      titles.addElement(title);
    }
    gridBorder._width = hozDistance * numberOfItemPerRow;
    gridBorder._height = verDistance * (items.size() / numberOfItemPerRow);
  }

  public void removeItem(int index) {
    if (items.size() > index) {
      items.removeElementAt(index);
    }
    if (images.size() > index) {
      images.removeElementAt(index);
    }
    if (brightImages.size() > index) {
      brightImages.removeElementAt(index);
    }
    if (titles.size() > index) {
      titles.removeElementAt(index);
    }
    gridBorder._width = hozDistance * numberOfItemPerRow;
    gridBorder._height = verDistance * (items.size() / numberOfItemPerRow);

    if (currentSelectedIndex > items.size() - 1) {
      currentSelectedIndex = items.size() - 1;
      if (currentSelectedIndex < 0) {
        currentSelectedIndex = 0;
      }
    }
  }

  public void setEnableScroll(boolean enableScroll1) {
    this.enableScroll = enableScroll1;
  }

  public boolean isEnableScroll() {
    return enableScroll;
  }

  public GameImage getImageOfItem(int index) {
    if (images.size() < index) {
      return null;
    }
    return (GameImage) images.elementAt(index);
  }

  public GameImageArray getImageOfAllItem() {
    GameImageArray results = GameImageArray.create(images.size());
    for (int i = 0; i < images.size(); i++) {
      results.set(i, (GameImage) images.elementAt(i));
    }
    return results;
  }

  public int getNumberOfItem() {
    return items.size();
  }

  public String getTitleOfIndex(int index) {
    if (titles == null || titles.size() < index) {
      return "";
    }
    return titles.elementAt(index).toString();
  }

  public void setNextTabWhenEndRow(MultiTab multiTab1) {
    if (multiTab1 != null) {
      this.multiTab = multiTab1;
      this.isNextTabWhenEndRow = true;
    } else {
      this.isNextTabWhenEndRow = true;
    }
  }

  public void setBackTabWhenBeginRow(MultiTab multiTab1) {
    if (multiTab1 != null) {
      this.multiTab = multiTab1;
      this.isBackTabWhenBeginRow = true;
    } else {
      this.isBackTabWhenBeginRow = true;
    }
  }

  public void setDisplayTitle(boolean isDisplayTitle) {
    this.displayTitle = isDisplayTitle;
  }

  public boolean isDisplayTitle() {
    return displayTitle;
  }

  public int getCurrentSelectedIndex() {
    return currentSelectedIndex;
  }

  public void setCurrentSelectedIndex(int currentSelectedIndex1) {
    this.currentSelectedIndex = currentSelectedIndex1;
  }

  public void setEventListener(EventListener eventListener1) {
    this.eventListener = eventListener1;
  }

  public int getBrightLevel() {
    return brightLevel;
  }

  public void setBrightLevel(int brightLevel1) {
    this.brightLevel = brightLevel1;
  }

  public void setShowToolTipTime(int showToolTipTime1) {
    this.showToolTipTime = showToolTipTime1;
  }

  public int getShowToolTipTime() {
    return showToolTipTime;
  }

  public void setEventNumbers(IntArray eventNumbers1) {
    this.eventNumbers = eventNumbers1;
  }

  public IntArray getEventNumbers() {
    return eventNumbers;
  }

  public void setEvent(int eventIndex, int number) {
    if (eventNumbers != null) {
      eventNumbers.set(eventIndex, number);
    }
  }

  public int getDx() {
    return dx;
  }

  public void setDx(int dx1) {
    this.dx = dx1;
  }

  public int getDy() {
    return dy;
  }

  public void setDy(int dy1) {
    this.dy = dy1;
  }

  public int getHozDistance() {
    return hozDistance;
  }

  public void setHozDistance(int hozDistance1) {
    this.hozDistance = hozDistance1;
  }

  public int getVerDistance() {
    return verDistance;
  }

  public void setVerDistance(int verDistance1) {
    this.verDistance = verDistance1;
  }

  public int getNumberOfItemPerRow() {
    return numberOfItemPerRow;
  }

  public void setNumberOfItemPerRow(int numberOfItemPerRow1) {
    this.numberOfItemPerRow = numberOfItemPerRow1;
  }

  public void draw(Graphics g) {
    for (int i = 0; i < items.size(); i++) {
      Sprite item = (Sprite) items.elementAt(i);
      int x1 = dx + hozDistance * (i % numberOfItemPerRow);
      int y1 = dy + verDistance * (i / numberOfItemPerRow);

      if (y1 < borderY) {
        continue;
      }

      item.paint(g);
      if (eventNumbers != null) {
        drawEventNumbers(g, eventNumbers.get(i), item.getRealX() + item.getWidth(), item.getRealY());
      }

      if (isDisplayTitle() && titles != null && titles.size() > i) {
        if (currentSelectedIndex == i) {
          text8.setBold(true);
          text8.drawString2(g, String.valueOf(titles.elementAt(i)), _focusFgColor, x1, y1 + item.getHeight() / 2 + 10, GameConstants.CENTER_ANCHOR);
          text8.setBold(false);
        } else {
          text8.drawString2(g, String.valueOf(titles.elementAt(i)), _forceGroundColor, x1, y1 + item.getHeight() / 2 + 10, GameConstants.CENTER_ANCHOR);
        }
      }

      if (_hasBorder) {
        g.setColor(borderColor);
        g.drawRect(x1 - hozDistance / 2, y1 - verDistance / 2, hozDistance, verDistance);
      }
    }

    if (tootltip != null && stopTime > showToolTipTime) {
      int x1 = dx + hozDistance * (currentSelectedIndex % numberOfItemPerRow);
      int y1 = dy + verDistance * (currentSelectedIndex / numberOfItemPerRow);
      drawToolTip(g, text8, tootltip.getRow(currentSelectedIndex), x1, y1);
    }
  }

  public void drawEventNumbers(Graphics g, int number, int x1, int y1) {
    if (number > 0) {
      g.drawImage(roundRedImage, x1 - 2, y1 + 2, GameConstants.CENTER_ANCHOR);
      text8.drawString2(g, fillNumberByLength(number, 2), GameColor.WHITE_CODE, x1, y1, GameConstants.CENTER_ANCHOR);
    }
  }

  private String fillNumberByLength(int number, int length) {
    String strNumber = String.valueOf(number);
    int tmp = length - strNumber.length();
    if (tmp > 0) {
      for (int i = 0; i < tmp; i++) {
        strNumber = "0" + strNumber;
      }
    }
    return strNumber;
  }

  public void setToolTip(TwoDimensionString tootltip1) {
    this.tootltip = tootltip1;
  }

  public static void drawToolTip(Graphics g, ImageFont text, StringArray tooltipText, int x, int y) {
    int maxWith = 0;
    for (int i = 0; i < tooltipText.len(); i++) {
      int toolTipWidth = text.stringWidth(tooltipText.get(i));
      if (toolTipWidth > maxWith) {
        maxWith = toolTipWidth;
      }
    }

    for (int i = 0; i < tooltipText.len(); i++) {
      g.setColor(0x3CA446);
      g.fillRect(x - maxWith / 2 - 2, y - 9 + 15 * i, maxWith + 8, 20);
    }

    for (int i = 0; i < tooltipText.len(); i++) {
      text.drawString2(g, tooltipText.get(i), GameColor.WHITE_CODE, x, y - 7 + 15 * i, GameConstants.TOP_HCENTER_ANCHOR);
    }
  }

  public void pointerPressed(Sprite source, int x1, int y1) {
    stopTime = 0;
    pressedPoint._x = x1;
    pressedPoint._y = y1;
    timePressed = (int) System.currentTimeMillis();

    for (int i = 0; i < items.size(); i++) {
      Sprite item = (Sprite) items.elementAt(i);
      if (item.contains(x1, y1)) {
        currentSelectedIndex = i;
        break;
      }
    }
    updateFocus();
  }

  public void pointerReleased(Sprite source, int x1, int y1) {
    if (items.size() == 0) {
      return;
    }

    stopTime = 0;
    // Process for drag
    int moveLength = 4 * (y1 - pressedPoint._y);
    rowMove = moveLength / verDistance;

    // Process for choose item
    Sprite item = (Sprite) items.elementAt(currentSelectedIndex);
    if (item.contains(x1, y1)) {
      if (eventListener != null) {
        if (titles != null && titles.size() > currentSelectedIndex) {
          eventListener.onActionPerform(new Event(this, String.valueOf(titles.elementAt(currentSelectedIndex))));
        } else {
          eventListener.onActionPerform(new Event(this, String.valueOf(currentSelectedIndex)));
        }
      }
      return;
    }
  }

  private void updateFocus() {
    if (images != null) {
      for (int i = 0; i < items.size(); i++) {
        if (images.size() > i) {
          Sprite item = (Sprite) items.elementAt(i);
          item.setImage((GameImage) images.elementAt(i));
        }
      }
    }

    if (currentSelectedIndex < 0) {
      currentSelectedIndex = 0;
    }

    if (brightImages != null && brightImages.size() > currentSelectedIndex) {
      Sprite item = (Sprite) items.elementAt(currentSelectedIndex);
      item.setImage((GameImage) brightImages.elementAt(currentSelectedIndex));
    }
    checkScroll();
  }

  public void keyReleased(Sprite source, int keyCode) {
    stopTime = 0;
    switch (keyCode) {
    case Key.LEFT:
      int oldRow1 = (currentSelectedIndex / numberOfItemPerRow) + 1;
      int oldIndex1 = currentSelectedIndex;
      currentSelectedIndex = (currentSelectedIndex - 1 < 0) ? 0 : currentSelectedIndex - 1;
      int newRow1 = (currentSelectedIndex / numberOfItemPerRow) + 1;
      if (newRow1 != oldRow1 && isBackTabWhenBeginRow) {
        currentSelectedIndex = oldIndex1;
      }
      if (((newRow1 != oldRow1) || (oldIndex1 == 0)) && isBackTabWhenBeginRow) {
        multiTab.previousTab();
      }
      break;
    case Key.RIGHT:
      int oldRow = (currentSelectedIndex / numberOfItemPerRow) + 1;
      int oldIndex = currentSelectedIndex;
      currentSelectedIndex = (currentSelectedIndex + 1 > items.size() - 1) ? items.size() - 1 : currentSelectedIndex + 1;
      int newRow = (currentSelectedIndex / numberOfItemPerRow) + 1;
      if (newRow != oldRow && isNextTabWhenEndRow) {
        currentSelectedIndex = oldIndex;
      }
      if (((newRow != oldRow) || (oldIndex == items.size() - 1)) && isNextTabWhenEndRow) {
        multiTab.nextTab();
      }
      break;
    case Key.DOWN:
      down();
      break;
    case Key.UP:
      up();
      break;
    }
    updateFocus();
  }

  private void down() {
    currentSelectedIndex = (currentSelectedIndex + numberOfItemPerRow > items.size() - 1) ? currentSelectedIndex : currentSelectedIndex + numberOfItemPerRow;
  }

  private void up() {
    currentSelectedIndex = (currentSelectedIndex - numberOfItemPerRow < 0) ? currentSelectedIndex : currentSelectedIndex - numberOfItemPerRow;
  }

  private void checkScroll() {
    if (!enableScroll) {
      return;
    }

    int currentRow = (currentSelectedIndex / numberOfItemPerRow) + 1;
    if (dy + currentRow * verDistance > GameConstants.SCREEN_HEIGHT - 25) {
      dy -= verDistance;
      for (int i = 0; i < items.size(); i++) {
        Sprite item = (Sprite) items.elementAt(i);
        item.move(0, -verDistance);
      }
    } else if (dy + (currentRow - 1) * verDistance < borderY + verDistance / 2) {
      dy += verDistance;
      for (int i = 0; i < items.size(); i++) {
        Sprite item = (Sprite) items.elementAt(i);
        item.move(0, verDistance);
      }
    }
  }

  public void doTask() {
    stopTime += 30;
    if (rowMove > 0) {
      down();
      rowMove--;
      updateFocus();
    } else if (rowMove < 0) {
      up();
      rowMove++;
      updateFocus();
    }
  }

  public Sprite detroy() {
    items = null;
    images = null;
    brightImages = null;
    titles = null;
    tootltip = null;
    eventNumbers = null;
    return super.detroy();
  }
}
